/**
 * Copyright (C) 2018 Infinite Automation Software. All rights reserved.
 */
package com.serotonin.m2m2.web.mvc.spring.security;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.switchuser.AuthenticationSwitchUserEvent;
import org.springframework.stereotype.Component;

import com.infiniteautomation.mango.spring.events.MangoHttpSessionDestroyedEvent;
import com.serotonin.m2m2.Common;
import com.serotonin.m2m2.db.dao.UserDao;
import com.serotonin.m2m2.i18n.TranslatableMessage;
import com.serotonin.m2m2.rt.event.type.SystemEventType;
import com.serotonin.m2m2.vo.User;

/**
 * Class to handle all security related events.
 *
 * @author Terry Packer
 */
@Component
public class MangoSecurityEventListener {

    private static final Log LOG = LogFactory.getLog(MangoSecurityEventListener.class);
    private final UserDao userDao;

    @Autowired
    public MangoSecurityEventListener(UserDao userDao) {
        this.userDao = userDao;
    }

    /**
     * Listen for events generated by the MangoSwitchUserFilter
     * @param event
     */
    @EventListener
    private void handleAuthenticationSwitchUserEvent(AuthenticationSwitchUserEvent event) {
        LOG.info("Switch User: '" + ((User)event.getAuthentication().getPrincipal()).getUsername() + "' switched to '" + event.getTargetUser().getUsername() + "'");
    }

    @EventListener
    private void handleAuthenticationSuccessEvent(AuthenticationSuccessEvent event) {
        Authentication authentication = event.getAuthentication();

        String remoteAddress = "";
        Object details = authentication.getDetails();
        if (details instanceof WebAuthenticationDetails) {
            WebAuthenticationDetails webDetails = (WebAuthenticationDetails) authentication.getDetails();
            remoteAddress = webDetails.getRemoteAddress();
        }

        if (authentication instanceof UsernamePasswordAuthenticationToken) {
            User user = (User) authentication.getPrincipal();

            // Update the last login time.
            userDao.recordLogin(user);

            SystemEventType eventType = new SystemEventType(SystemEventType.TYPE_USER_LOGIN, user.getId());
            TranslatableMessage message = new TranslatableMessage("event.login", user.getUsername(), remoteAddress);
            SystemEventType.raiseEvent(eventType, Common.timer.currentTimeMillis(), true, message);
        }
    }

    @EventListener
    private void handleHttpSessionDestroyedEvent(MangoHttpSessionDestroyedEvent event) {
        for (Authentication authentication : event.getAuthentications()) {
            if (authentication instanceof UsernamePasswordAuthenticationToken && !event.isUserMigratedToNewSession()) {
                User user = (User) authentication.getPrincipal();
                SystemEventType eventType = new SystemEventType(SystemEventType.TYPE_USER_LOGIN, user.getId());
                SystemEventType.returnToNormal(eventType, Common.timer.currentTimeMillis());
            }
        }
    }

}
